/*
 *      lightlog.c
 *
 *      Copyright 2009 Daniele Ricci <denn86@gmail.com>, Luca Saccagi <luksak86@gmail.com>
 *
 *      This program is free software; you can redistribute it and/or modify
 *      it under the terms of the GNU General Public License as published by
 *      the Free Software Foundation; either version 2 of the License, or
 *      (at your option) any later version.
 *
 *      This program is distributed in the hope that it will be useful,
 *      but WITHOUT ANY WARRANTY; without even the implied warranty of
 *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *      GNU General Public License for more details.
 *
 *      You should have received a copy of the GNU General Public License
 *      along with this program; if not, write to the Free Software
 *      Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 *      MA 02110-1301, USA.
 */




#ifndef _LIGHTLOGDEF
#define _LIGHTLOGDEF

#include "lightlog.h"


STATIC int lightlog_record_write(char *filepath, int priority, int facility, char *pattern ,char *TIMESTAMP, int TYPEID, char *HEADER, char *SUBJECT, char *ACTION1, char *OBJECT, char *ACTION2, char *TARGET){
	FILE *fl;
	char default_pattern[] = "[%s]%s(%d)%s%s%s%s%s%s\n";
	char *using_pattern = NULL;
	char *priority_string = NULL;

	if(!lightlog_priority_check(priority)) return 1;
	if((fl = lightlog_file_openTS(filepath)) == NULL) return 2;
	
	using_pattern = (pattern == NULL) ? default_pattern : pattern ;
	priority_string = priority_str[priority];

	if(fprintf(fl,using_pattern,priority_string,TIMESTAMP,TYPEID,HEADER,SUBJECT,ACTION1,OBJECT,ACTION2,TARGET) < 0 ){
		lightlog_file_closeTS(fl);
		return 3;
	}

	lightlog_file_closeTS(fl);
	return 0;
}

STATIC char *lightlog_idmef_alert_create(char *analyzerid, int messageid, char *ANALYZER, char *CREATETIME, char *CLASSIFICATION, char *_children){
	/////////////////////////////////////////////////////////////////////ANALYZERID_ALERTID///////////////////ANALYZERID/////////////////////TIMESTAMPHEX//TIMESTAMP
	char default_pattern[] = "<IDMEF-Message version=\"1.0\"><Alert messageid=\"%s_%06d\">%s%s%s%s</Alert></IDMEF-Message>\n";
	char *using_pattern = NULL;
	char *priority_string = NULL;
	char *out = NULL;

	out = (char*)calloc(IDMEF_MAXSIZE,sizeof(char));
	sprintf(out,default_pattern,analyzerid,messageid,ANALYZER,CREATETIME,CLASSIFICATION,(_children == NULL ? "" : _children));
	free(ANALYZER);
	free(CLASSIFICATION);
	free(CREATETIME);
	_children == NULL ? 0 : free(_children);
	return out;
}

STATIC char *lightlog_idmef_child(char *NAME, char *pattern ,char *ATTR1VAL, char *ATTR2VAL, char *_content,int freeATTR1,int freeATTR2, int free_content){
	///////////////////////////////NAME//_content///NAME
	char default_pattern[] = "<%s>%s</%s>\0";
	char empty[] = "";
	char *out = NULL;

	
	
	/* You MUST valorize pattern string if you wish adding attributes */
	if((pattern == NULL) && ((ATTR1VAL!=NULL)||(ATTR2VAL!=NULL))) return NULL;

	_content == NULL ? (free_content = false, _content = empty) : 0;

	if(pattern == NULL){
		out=(char*)calloc(strlen(default_pattern)+(strlen(NAME)*2)+strlen(_content)+1,sizeof(char));	
		sprintf(out,default_pattern,NAME,_content,NAME);
	}else{
		out=(char*)calloc(strlen(pattern)+(strlen(NAME)*2)+strlen(ATTR1VAL)+strlen(ATTR2VAL)+strlen(_content)+1,sizeof(char));	
		sprintf(out,pattern,NAME,ATTR1VAL,ATTR2VAL,_content,NAME);
	}
	
	freeATTR1 == 1 ? free(ATTR1VAL) : 0;
	freeATTR2 == 1 ? free(ATTR2VAL) : 0;
	free_content == 1 ? free(_content) : 0;
	return out;
}

STATIC char *lightlog_idmef_brothers(char *_children0,char *_children1,char *_children2,char *_children3){
	char *out = NULL;
	char empty[] = "";
	int c0,c1,c2,c3;

	_children0 == NULL ? (_children0 = empty, c0 = false) : (c0 = true);
	_children1 == NULL ? (_children1 = empty, c1 = false) : (c1 = true);
	_children2 == NULL ? (_children2 = empty, c2 = false) : (c2 = true);
	_children3 == NULL ? (_children3 = empty, c3 = false) : (c3 = true);
	
	out=(char*)calloc(strlen(_children0)+strlen(_children1)+strlen(_children2)+strlen(_children3)+1,sizeof(char));
	sprintf(out,"%s%s%s%s\0",_children0,_children1,_children2,_children3);	

	c0 ? free(_children0) : 0;
	c1 ? free(_children1) : 0;
	c2 ? free(_children2) : 0;
	c3 ? free(_children3) : 0;
	return out;
}

STATIC int lightlog_idmef_write(char *filepath, int priority, int facility, char *IDMEF_MESSAGE){
	FILE *fl;
	
	if(!lightlog_priority_check(priority)) return 1;
	if((fl = lightlog_file_openTS(filepath)) == NULL) return 2;

	if(fprintf(fl,"%s",IDMEF_MESSAGE) < 0 ){
		lightlog_file_closeTS(fl);
		return 3;
	}

	lightlog_file_closeTS(fl);
	return 0;
}

STATIC int Localtime_m(struct tm *_Tm,time_t *_Time){

#ifdef _WIN32
	return localtime_s(_Tm,_Time);
#else
	return localtime_r(_Time,_Tm);
#endif
}

STATIC char *lightlog_timestamp(char *out, char *pattern){
	time_t now;
	struct tm lnow;
	char *TIMESTAMP = NULL;
	char default_pattern[] = "[%04d-%02d-%02d,%02d:%02d:%02d]\0";
	char *using_pattern = NULL;

	using_pattern = (pattern == NULL) ? default_pattern : pattern ;
	TIMESTAMP = (out == NULL) ? (char *)calloc(MAX_TSLEN,sizeof(char)) : out;
	time(&now);
	Localtime_m(&lnow,&now);
	sprintf(TIMESTAMP,using_pattern,(lnow.tm_year+1900),(lnow.tm_mon+1),(lnow.tm_mday),(lnow.tm_hour),(lnow.tm_min),(lnow.tm_sec));
	
	return TIMESTAMP;
}

STATIC char *lightlog_timestamp_hex(char *out){
	char *return_string;
	struct timeval tspc;
	
	gettimeofday(&tspc,NULL);
	return_string = (out == NULL) ? (char *)calloc(sizeof(char),22) : out;
	sprintf(return_string,"0x%08lX.0x%08lX",tspc.tv_sec,tspc.tv_usec);
	return return_string;
}

STATIC void lightlog_timestamp_destroy(char *TIMESTAMP){
	TIMESTAMP != NULL ? free(TIMESTAMP) : 0;
	return;
}

STATIC int lightlog_priority_check(int priority){
	if(WTL < 0)	return (priority + WTL) == 0 ? true : false;
	else return priority <= WTL ? true : false;
}

STATIC void lightlog_priority_set(int priority){
	WTL = priority;
	return;
}

STATIC int lightlog_priority_get(void){
	return WTL;
}

STATIC FILE *lightlog_file_openTS(char *filepath){
	FILE *logfile = NULL;
	
	while((logfile=fopen(filepath,"at"))==NULL){
		usleep(10);
	}
	#ifdef _WIN32
	_lock_file(logfile);
	#else
	flock(logfile,LOCK_EX);
	#endif
	return logfile;
}
STATIC int lightlog_file_closeTS(FILE *filetoclose){
	#ifdef _WIN32
	_unlock_file(filetoclose);
	#else
	flock(filetoclose,LOCK_UN);
	#endif
	return fclose(filetoclose);
}


STATIC char *lightlog_rotation(char *origpath,char *buffer,char rotationtype, int maxfilesize){
	struct tm lnow;
	struct stat stbuf;
	time_t now;
	int i = 0;
	int newfile = 0;

	switch(rotationtype){
		case 'y'://year rotation
			time(&now);
			Localtime_m(&lnow,&now);
			lnow.tm_year+=1900;
			lnow.tm_mon++;
			sprintf(buffer,"%s.%04d\0",origpath,lnow.tm_year);
			if(maxfilesize == 0) break;
			/* Due to file size, retrieving the right origpath */
			newfile = stat(buffer,&stbuf);
			for(i=1; (stbuf.st_size >= maxfilesize) && (newfile == 0); i++){
				sprintf(buffer,"%s.%04d.%02d\0",origpath,(lnow.tm_year),i);
				newfile = stat(buffer,&stbuf);
			}
			break;
		case 'm'://month rotation
			time(&now);
			Localtime_m(&lnow,&now);
			lnow.tm_year+=1900;
			lnow.tm_mon++;
			sprintf(buffer,"%s.%04d%02d\0",origpath,lnow.tm_year,lnow.tm_mon);
			if(maxfilesize == 0) break;
			/* Due to file size, retrieving the right origpath */
			newfile = stat(buffer,&stbuf);
			for(i=1; (stbuf.st_size >= maxfilesize) && (newfile == 0); i++){
				sprintf(buffer,"%s.%04d%02d_%02d\0",origpath,lnow.tm_year,lnow.tm_mon,i);
				newfile = stat(buffer,&stbuf);
			}
			break;
		case 'd'://day rotation
			time(&now);
			Localtime_m(&lnow,&now);
			lnow.tm_year+=1900;
			lnow.tm_mon++;
			sprintf(buffer,"%s.%04d%02d%02d\0",origpath,lnow.tm_year,lnow.tm_mon,lnow.tm_mday);
			if(maxfilesize == 0) break;
			/* Due to file size, retrieving the right origpath */
			newfile = stat(buffer,&stbuf);
			for(i=1; (stbuf.st_size >= maxfilesize) && (newfile == 0); i++){
				sprintf(buffer,"%s.%04d%02d%02d_%02d\0",origpath,lnow.tm_year,lnow.tm_mon,lnow.tm_mday,i);
				newfile = stat(buffer,&stbuf);
			}
			break;
		case 's'://size rotation
			if(maxfilesize == 0) break;
			/* Due to file size, retrieving the right origpath */
			strcpy(buffer,origpath);
			newfile = stat(buffer,&stbuf);
			for(i=1; (stbuf.st_size >= maxfilesize) && (newfile == 0); i++){
				sprintf(buffer,"%s.%03d\0",origpath,i);
				newfile = stat(buffer,&stbuf);
			}
			break;
	}
	return buffer;
}


#endif
